package com.qiangesoft.weather.gaode;

import com.qiangesoft.weather.gaode.entity.Weather;
import com.qiangesoft.weather.gaode.entity.WeatherForecast;
import com.qiangesoft.weather.gaode.constant.WeatherConstant;
import com.qiangesoft.weather.gaode.constant.WeatherType;
import com.qiangesoft.weather.gaode.model.Forecast;
import com.qiangesoft.weather.gaode.model.GaoDeResult;
import com.qiangesoft.weather.gaode.model.Live;
import com.qiangesoft.weather.gaode.service.IWeatherForecastService;
import com.qiangesoft.weather.gaode.service.IWeatherService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.List;

/**
 * 天气数据更新
 *
 * @author qiangesoft
 * @date 2023-07-18
 */
@Slf4j
@Component
public class WeatherTask {

    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private IWeatherService weatherService;
    @Autowired
    private IWeatherForecastService weatherForecastService;

    /**
     * 北京市
     * 城市编码表：doc/AMap_adcode_citycode.xlsx
     */
    private static final String AD_CODE = "110000";

    /**
     * 实况天气每小时更新多次
     * 每隔一小时执行一次
     */
    @Scheduled(cron = "0 0 0/1 * * ?")
    public void pullLive() {
        log.info("Pull live weather data begin==================>");
        long startTime = System.currentTimeMillis();

        // 拉取实时天气
        this.saveLive(AD_CODE);

        long endTime = System.currentTimeMillis();
        log.info("spend time:" + (endTime - startTime));
        log.info("Pull live weather data end<==================");
    }

    /**
     * 预报天气每天更新3次，分别在8、11、18点左右更新
     * 每天8、11、18点30分执行
     */
    @Scheduled(cron = "0 30 8,11,18 * * ?")
    public void pullForecast() {
        log.info("Pull forecast weather data begin==================>");
        long startTime = System.currentTimeMillis();

        // 拉取预报天气
        this.saveForecast(AD_CODE);

        long endTime = System.currentTimeMillis();
        log.info("spend time:" + (endTime - startTime));
        log.info("Pull forecast weather data end<==================");
    }

    /**
     * 预报天气
     *
     * @param adcode
     */
    private void saveForecast(String adcode) {
        StringBuilder sendUrl = new StringBuilder(WeatherConstant.WEATHER_URL)
                .append("?key=").append(GaoDeApi.KEY_VALUE)
                .append("&city=").append(adcode)
                .append("&extensions=all");
        ResponseEntity<GaoDeResult> responseEntity = restTemplate.getForEntity(sendUrl.toString(), GaoDeResult.class);
        // 请求异常，可能由于网络等原因
        HttpStatus statusCode = responseEntity.getStatusCode();
        if (!HttpStatus.OK.equals(statusCode)) {
            log.info("Request for Gaode interface error");
            return;
        }

        // 请求失败
        GaoDeResult gaoDeResult = responseEntity.getBody();
        String status = gaoDeResult.getStatus();
        if (!status.equals(GaoDeApi.SUCCESS)) {
            log.info("Request for Gaode interface failed");
            return;
        }

        List<Forecast> forecasts = gaoDeResult.getForecasts();
        if (CollectionUtils.isEmpty(forecasts)) {
            return;
        }

        // 预报天气
        Forecast forecast = forecasts.get(0);
        List<WeatherForecast> weatherForecastList = new ArrayList<>();
        List<Forecast.Cast> casts = forecast.getCasts();
        for (Forecast.Cast cast : casts) {
            WeatherForecast weatherForecast = new WeatherForecast();
            weatherForecast.setProvince(forecast.getProvince());
            weatherForecast.setCity(forecast.getCity());
            weatherForecast.setAdcode(forecast.getAdcode());
            weatherForecast.setDate(cast.getDate());
            weatherForecast.setWeek(cast.getWeek());
            weatherForecast.setDayWeather(cast.getDayweather());
            weatherForecast.setDayWeatherImg(WeatherType.getCodeByDes(cast.getDayweather()));
            weatherForecast.setNightWeather(cast.getNightweather());
            weatherForecast.setNightWeatherImg(WeatherType.getCodeByDes(cast.getNightweather()));
            weatherForecast.setDayTemp(cast.getDaytemp());
            weatherForecast.setNightTemp(cast.getNighttemp());
            weatherForecast.setDayWind(cast.getDaywind());
            weatherForecast.setNightWind(cast.getNightwind());
            weatherForecast.setDayPower(cast.getDaypower());
            weatherForecast.setNightPower(cast.getNightpower());
            weatherForecast.setReportTime(forecast.getReporttime());
            weatherForecastList.add(weatherForecast);
        }
        weatherForecastService.saveBatch(weatherForecastList);
    }

    /**
     * 实时天气
     *
     * @param adcode
     */
    private void saveLive(String adcode) {
        StringBuilder sendUrl = new StringBuilder(WeatherConstant.WEATHER_URL)
                .append("?key=").append(GaoDeApi.KEY_VALUE)
                .append("&city=").append(adcode)
                .append("&extensions=base");
        ResponseEntity<GaoDeResult> responseEntity = restTemplate.getForEntity(sendUrl.toString(), GaoDeResult.class);
        // 请求异常，可能由于网络等原因
        HttpStatus statusCode = responseEntity.getStatusCode();
        if (!HttpStatus.OK.equals(statusCode)) {
            log.info("Request for Gaode interface error");
            return;
        }

        // 请求失败
        GaoDeResult gaoDeResult = responseEntity.getBody();
        String status = gaoDeResult.getStatus();
        if (!status.equals(GaoDeApi.SUCCESS)) {
            log.info("Request for Gaode interface failed");
            return;
        }

        List<Live> lives = gaoDeResult.getLives();
        if (CollectionUtils.isEmpty(lives)) {
            return;
        }

        // 实况天气
        Live live = lives.get(0);
        Weather weather = new Weather();
        weather.setProvince(live.getProvince());
        weather.setCity(live.getCity());
        weather.setAdcode(live.getAdcode());
        weather.setWeather(live.getWeather());
        weather.setWeatherImg(WeatherType.getCodeByDes(live.getWeather()));
        weather.setTemperature(live.getTemperature());
        weather.setWindDirection(live.getWinddirection());
        weather.setWindPower(live.getWindpower());
        weather.setHumidity(live.getHumidity());
        weather.setReportTime(live.getReporttime());
        weatherService.save(weather);
    }

}